[XENBUS] Don't perform normal state-machine transitions and
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Fri, 29 Sep 2006 08:14:28 +0000 (09:14 +0100)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Fri, 29 Sep 2006 08:14:28 +0000 (09:14 +0100)
notifications during shutdown. When rootfs goes away this can
cause the system to hang, as we notify userspace etc.
Instead we forcibly reset the state machine back to state Closed
if we are a frontend driver, to get the backend to release
resources. Necessary if we are going to kexec.
Signed-off-by: Keir Fraser <keir@xensource.com>
linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c

index 4c44d7608d4b2e165748dc916585b890a45fafbd..83630ee2ec8bfcae0a114b5f665a95c8586af2fd 100644 (file)
@@ -273,7 +273,7 @@ static void backend_changed(struct xenbus_device *dev,
                        xenbus_dev_fatal(dev, -ENODEV, "bdget failed");
 
                down(&bd->bd_sem);
-               if (info->users > 0 && system_state == SYSTEM_RUNNING)
+               if (info->users > 0)
                        xenbus_dev_error(dev, -EBUSY,
                                         "Device in use; refusing to close");
                else
index bcd1f6df06845f51f0b0b77e2ffdd83f9cadd796..87c9e6ed90497cc281911543fa633f98015820d2 100644 (file)
@@ -322,6 +322,20 @@ static void otherend_changed(struct xenbus_watch *watch,
        DPRINTK("state is %d (%s), %s, %s", state, xenbus_strstate(state),
                dev->otherend_watch.node, vec[XS_WATCH_PATH]);
 
+       /*
+        * Ignore xenbus transitions during shutdown. This prevents us doing
+        * work that can fail e.g., when the rootfs is gone.
+        */
+       if (system_state > SYSTEM_RUNNING) {
+               struct xen_bus_type *bus = bus;
+               bus = container_of(dev->dev.bus, struct xen_bus_type, bus);
+               /* If we're frontend, drive the state machine to Closed. */
+               /* This should cause the backend to release our resources. */
+               if ((bus == &xenbus_frontend) && (state == XenbusStateClosing))
+                       xenbus_frontend_closed(dev);
+               return;
+       }
+
        if (drv->otherend_changed)
                drv->otherend_changed(dev, state);
 }